#include "devicedlg.hpp"
#include "ui_devicedlg.h"
#include <qevent.h>
#include <qmessagebox.h>
#include <qsettings.h>
#include "qdbusmodel.h"
#include "dbuspath.hpp"
#include "qdbusviewer.h"
DeviceDlg::DeviceDlg(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DeviceDlg),
    m_bus("NONE")
{
    ui->setupUi(this);
    pathsModel = Q_NULLPTR;
    connect(ui->cbType,&QComboBox::currentTextChanged,this,&DeviceDlg::on_cbType_currentTextChanged);

    QRegExp regExp("^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){0,3}$");
    ui->leHost->setValidator(new QRegExpValidator(regExp, ui->leHost));
    ui->leHost->setInputMask("000.000.000.000");
    ui->leHost->setText("127.0.0.1");
    ui->leHost->setEnabled(true);
    ui->gbHost->setVisible (false);
    servicesModel = new QStringListModel(this);
    pathsProxyModel = Q_NULLPTR;


    servicesProxyModel = new ServicesProxyModel(this);
    servicesProxyModel->setSourceModel(servicesModel);
    servicesProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);

    ui->tvService->setModel(servicesProxyModel);
    // Make services grid view behave like a list view with headers
    ui->tvService->verticalHeader()->hide();
    ui->tvService->horizontalHeader()->setStretchLastSection(true);
    ui->tvService->setShowGrid(false);
    // Sort service list by default
    ui->tvService->setSortingEnabled(true);
    ui->tvService->sortByColumn(0, Qt::AscendingOrder);
    connect(ui->leServiceFilter, SIGNAL(textChanged(QString)), servicesProxyModel, SLOT(setFilterFixedString(QString)));
    connect(ui->tvService->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this, SLOT(serviceChanged(QModelIndex)));

//    restoreSettings();
//    adjustSize();

}

void DeviceDlg::saveState() const
{
#ifdef Q_OS_MAC
    QSettings settings;
#else
    QSettings settings("DeviceDlg_tools.ini",QSettings::IniFormat);
#endif
    settings.setValue(Setting_DeviceDlg_main, saveGeometry());
    settings.beginGroup(Setting_DeviceDlg_Value);
    settings.setValue(Setting_DeviceDlg_Host_Type,ui->cbType->currentText ().toLatin1 ());
    settings.setValue(Setting_DeviceDlg_Host_IP,ui->leHost->text ().toLatin1 ());
    settings.setValue(Setting_DeviceDlg_Host_Port,ui->lePort->text ().toLatin1 ());
    settings.endGroup();
}
void DeviceDlg::restoreSettings()
{
#ifdef Q_OS_MAC
    QSettings settings;
#else
    QSettings settings("DeviceDlg_tools.ini",QSettings::IniFormat);
#endif
    restoreGeometry(settings.value(Setting_DeviceDlg_main).toByteArray());
    settings.beginGroup(Setting_DeviceDlg_Value);
    if(settings.value(Setting_DeviceDlg_Host_Type).toString ().isEmpty ())
    {
        ui->cbType->setCurrentText (DBUS_NAME_SESSION);
    }else
    {
        ui->cbType->setCurrentText (settings.value(Setting_DeviceDlg_Host_Type).toString ());
    }

    if(settings.value(Setting_DeviceDlg_Host_IP).toString ().isEmpty ())
    {
        ui->leHost->setText ("127.0.0.1");
    }else
    {
        ui->leHost->setText (settings.value(Setting_DeviceDlg_Host_IP).toString ());
    }
    if(settings.value(Setting_DeviceDlg_Host_Port).toString ().isEmpty ())
    {
        ui->lePort->setText ("12434");
    }else
    {
        ui->lePort->setText (settings.value(Setting_DeviceDlg_Host_Port).toString ());
    }
    settings.endGroup();
    connect2DBus();
}

bool DeviceDlg::connect2DBus()
{
    if(m_bus.isConnected ())
    {
        QString strname = m_bus.name ();
        if(ui->cbType->currentText () == strname)
        {
            DbusPath dlg(m_bus);
            if(dlg.exec () == DbusPath::Accepted)
            {
                ui->leService->setText (dlg.getCurrentService ());
                ui->lePath->setText (dlg.getCurrentPath ());
                ui->leInterface->setText (dlg.getCurrentInterface ());
            }
            return true;
        }
        m_bus.disconnectFromBus (strname);
        m_bus = QDBusConnection("NONE");
    }
    if(ui->cbType->currentText () == DBUS_NAME_SESSION)
    {
        m_bus = QDBusConnection::connectToBus (QDBusConnection::SessionBus,DBUS_NAME_SESSION);
    }else if(ui->cbType->currentText () == DBUS_NAME_SYSTEM){
        m_bus = QDBusConnection::connectToBus (QDBusConnection::SystemBus,DBUS_NAME_SYSTEM);
    }else if(ui->cbType->currentText () == "Network")
    {
        QString strAddr = QString("tcp:host=%1,port=%2").arg (ui->leHost->text ()).arg (ui->lePort->text ());
        m_bus = QDBusConnection::connectToBus (strAddr,strAddr);
    }
    if(m_bus.isConnected ())
    {
        const QStringList serviceNames = m_bus.interface()->registeredServiceNames();
        QStringList strlist;
        QRegExp re(":[0-9]*\\.[0-9]+");
        foreach (QString var, serviceNames) {
            if(re.exactMatch (var))
            {
            }
            else if(var =="org.freedesktop.DBus")
            {
            }
            else
            {
                strlist<<var;
            }
        }
        servicesModel->setStringList(strlist);
        return true;
    }else
    {
        return false;

    }

}
DeviceDlg::~DeviceDlg()
{

    delete servicesModel;
    delete servicesProxyModel;
    if(pathsModel!=Q_NULLPTR)
        delete pathsModel;
    delete pathsProxyModel;
    delete ui;
}

void DeviceDlg::on_cbType_currentTextChanged(const QString & text)
{
    if(ui->cbType->currentIndex()==2)
    {
        ui->gbHost->setVisible (true);
    }else
    {
        ui->gbHost->setVisible (false);
    }
    adjustSize();
}
void DeviceDlg::on_pushButton_clicked()
{
    if(!connect2DBus())
    {
        ui->leService->setText ("");
        ui->lePath->setText ("");
        ui->leInterface->setText ("");
        QMessageBox::critical (this,"error","DBus connect fail",QMessageBox::Ok);
    }
}

QString DeviceDlg::getCurrentInterface() const
{
    return currentInterface;
}

QString DeviceDlg::getCurrentPath() const
{
    return currentPath;
}

QString DeviceDlg::getCurrentService() const
{
    return currentService;
}

QDBusConnection DeviceDlg::bus() const
{
    return m_bus;
}
void DeviceDlg::on_btOk_clicked()
{
    currentService = ui->leService->text ();
    currentPath = ui->lePath->text ();
    currentInterface = ui->leInterface->text ();
    if(!m_bus.isConnected () )
    {
        QMessageBox::critical (this,"error","DBus connect fail",QMessageBox::Ok);
        return;
    }
    if(currentService.isEmpty () || currentPath.isEmpty (),currentInterface.isEmpty ())
    {
        QMessageBox::critical (this,"error","Plaese select Dbus Object",QMessageBox::Ok);
        return;
    }

    this->accept ();

}

void DeviceDlg::on_btCancel_clicked()
{
    this->reject ();
}

void DeviceDlg::pathChanged(const QModelIndex &index)
{
    currentPath = index.data(Qt::UserRole+1).toString();
    if(index.data(Qt::UserRole+2).toBool ())
    {
        currentInterface = "";
    }else
    {
        currentInterface = index.data(Qt::DisplayRole).toString();
    }
    ui->leService->setText (currentService);
    ui->lePath->setText (currentPath);
    ui->leInterface->setText (currentInterface);
}

void DeviceDlg::serviceChanged(const QModelIndex &index)
{
    //    disconnect(ui->tree->selectionModel (),0,0, 0);
        delete ui->tvPath->model();
        currentService.clear();
        if (!index.isValid())
            return;
        currentService = index.data().toString();
        currentPath = "/";
        currentInterface = "";

        if(pathsModel!=Q_NULLPTR)
            delete pathsModel;


        pathsModel = new QDBusViewModel(currentService, m_bus,currentPath,currentInterface,false);
        pathsProxyModel = new ServicesProxyModel(this);
        pathsProxyModel->setSourceModel(pathsModel);
        pathsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);

        ui->tvPath->setModel(pathsProxyModel);
        ui->tvPath->expandAll ();
        ui->lePathFilter->setHidden (true);
        connect(ui->lePathFilter, SIGNAL(textChanged(QString)), pathsProxyModel, SLOT(setFilterFixedString(QString)));
        connect(ui->tvService->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
                this, SLOT(serviceChanged(QModelIndex)));

        connect(ui->tvPath->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
                this, SLOT(pathChanged(QModelIndex)));
}

void DeviceDlg::closeEvent(QCloseEvent *event)
{

}

void DeviceDlg::showEvent(QShowEvent *event)
{
    restoreSettings();
}

void DeviceDlg::hideEvent(QHideEvent *event)
{
    saveState();
}
